/*
 * *******************************************************
 *
 * 作者：hzy
 *
 * 开源地址：https://gitee.com/hzy6
 *
 * *******************************************************
 */

namespace HZY.Framework.Repository.EntityFramework.Repositories;

/// <summary>
/// 仓储接口
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IRepositoryBase<T> : IQueryRepository<T>
    where T : class, new()
{
    #region 插入

    /// <summary>
    /// 插入
    /// </summary>
    /// <param name="model"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    T? Insert(T? model, params string[]? ignorePropertyNames);

    /// <summary>
    /// 批量插入
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    int InsertRange(IEnumerable<T>? model);

    /// <summary>
    /// 插入
    /// </summary>
    /// <param name="model"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    Task<T?> InsertAsync(T? model, params string[]? ignorePropertyNames);

    /// <summary>
    /// 批量插入
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    Task<int> InsertRangeAsync(IEnumerable<T>? model);

    #endregion

    #region 更新

    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="model"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    int Update(T? model, params string[]? ignorePropertyNames);

    /// <summary>
    /// 根据实体id更新数据
    /// </summary>
    /// <param name="model"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    int UpdateById(T? model, params string[]? ignorePropertyNames);

    /// <summary>
    /// 更新，通过原模型 修改为新模型
    /// </summary>
    /// <param name="oldModel"></param>
    /// <param name="newModel"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    int Update(T? oldModel, T? newModel, params string[]? ignorePropertyNames);

    /// <summary>
    /// 更新 批量
    /// </summary>
    /// <param name="models"></param>
    /// <returns></returns>
    int UpdateRange(IEnumerable<T>? models);

    /// <summary>
    /// 更新部分字段 根据where 条件
    /// </summary>
    /// <param name="setPropertyCalls"></param>
    /// <param name="where"></param>
    /// <returns></returns>
    int UpdateBulk(Expression<Func<SetPropertyCalls<T>, SetPropertyCalls<T>>> setPropertyCalls,
        Expression<Func<T, bool>> where);

    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="model"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    Task<int> UpdateAsync(T? model, params string[]? ignorePropertyNames);

    /// <summary>
    /// 根据实体id更新数据
    /// </summary>
    /// <param name="model"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    Task<int> UpdateByIdAsync(T? model, params string[]? ignorePropertyNames);

    /// <summary>
    /// 更新，通过原模型 修改为新模型
    /// </summary>
    /// <param name="oldModel"></param>
    /// <param name="newModel"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    Task<int> UpdateAsync(T? oldModel, T? newModel, params string[]? ignorePropertyNames);

    /// <summary>
    /// 更新 批量
    /// </summary>
    /// <param name="models"></param>
    /// <returns></returns>
    Task<int> UpdateRangeAsync(IEnumerable<T>? models);

    /// <summary>
    /// 更新部分字段 根据where 条件
    /// </summary>
    /// <param name="setPropertyCalls"></param>
    /// <param name="where"></param>
    /// <returns></returns>
    Task<int> UpdateBulkAsync(Expression<Func<SetPropertyCalls<T>, SetPropertyCalls<T>>> setPropertyCalls,
        Expression<Func<T, bool>> where);

    #endregion

    #region 插入或者更新

    /// <summary>
    /// 插入或者添加 根据实体 主键判断是否添加还是修改
    /// </summary>
    /// <param name="model"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    T? InsertOrUpdate(T? model, params string[]? ignorePropertyNames);

    /// <summary>
    /// 插入或者添加 根据实体 主键判断是否添加还是修改
    /// </summary>
    /// <param name="model"></param>
    /// <param name="ignorePropertyNames"></param>
    /// <returns></returns>
    Task<T?> InsertOrUpdateAsync(T? model, params string[]? ignorePropertyNames);

    #endregion

    #region 删除

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    int Delete(T? model);

    /// <summary>
    /// 删除 批量
    /// </summary>
    /// <param name="models"></param>
    /// <returns></returns>
    int Delete(IEnumerable<T>? models);

    /// <summary>
    /// 删除 根据表达式
    /// </summary>
    /// <param name="expWhere"></param>
    /// <returns></returns>
    int Delete(Expression<Func<T, bool>> expWhere);

    /// <summary>
    /// 删除 根据表达式 直接 生成 delete from table  where 语句操作
    /// </summary>
    /// <param name="expWhere"></param>
    /// <returns></returns>
    int DeleteBulk(Expression<Func<T, bool>> expWhere);

    /// <summary>
    /// 删除 根据id
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    int DeleteById<TKey>(TKey key);

    /// <summary>
    /// 删除 根据 id集合
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <param name="keys"></param>
    /// <returns></returns>
    int DeleteByIds<TKey>(IEnumerable<TKey>? keys);

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    Task<int> DeleteAsync(T? model);

    /// <summary>
    /// 删除 批量
    /// </summary>
    /// <param name="models"></param>
    /// <returns></returns>
    Task<int> DeleteAsync(IEnumerable<T>? models);

    /// <summary>
    /// 删除 根据表达式
    /// </summary>
    /// <param name="expWhere"></param>
    /// <returns></returns>
    Task<int> DeleteAsync(Expression<Func<T, bool>> expWhere);

    /// <summary>
    /// 删除 根据表达式 直接 生成 delete from table  where 语句操作
    /// </summary>
    /// <param name="expWhere"></param>
    /// <returns></returns>
    Task<int> DeleteBulkAsync(Expression<Func<T, bool>> expWhere);

    /// <summary>
    /// 删除 根据 id
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    Task<int> DeleteByIdAsync<TKey>(TKey key);

    /// <summary>
    /// 删除 根据id集合
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <param name="keys"></param>
    /// <returns></returns>
    Task<int> DeleteByIdsAsync<TKey>(IEnumerable<TKey>? keys);

    #endregion

    #region 原生 sql 操作 添加、修改、删除

    /// <summary>
    /// 执行sql 返回受影响的行数 insert|update|delete
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    int ExecuteSqlRaw(string sql, params object[] parameters);

    /// <summary>
    /// 执行sql 返回受影响的行数 insert|update|delete
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    int ExecuteSqlRaw(string sql, IEnumerable<object> parameters);

    /// <summary>
    /// 执行sql 返回受影响的行数 insert|update|delete
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<int> ExecuteSqlRawAsync(string sql, CancellationToken cancellationToken = default);

    /// <summary>
    /// 执行sql 返回受影响的行数 insert|update|delete
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    Task<int> ExecuteSqlRawAsync(string sql, params object[] parameters);

    /// <summary>
    /// 执行sql 返回受影响的行数 insert|update|delete
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="parameters"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    Task<int> ExecuteSqlRawAsync(string sql, IEnumerable<object> parameters,
        CancellationToken cancellationToken = default);

    #endregion

    #region Sqlserver 数据批量拷贝

    /// <summary>
    /// Sqlserver 数据拷贝
    /// </summary>
    /// <param name="dataTable"></param>
    /// <param name="tableName"></param>
    /// <param name="dbTransaction"></param>
    void SqlServerBulkCopy(DataTable dataTable, string tableName, IDbTransaction? dbTransaction = null);

    /// <summary>
    /// Sqlserver 数据拷贝
    /// </summary>
    /// <param name="dataTable"></param>
    /// <param name="tableName"></param>
    /// <param name="dbTransaction"></param>
    /// <returns></returns>
    Task SqlServerBulkCopyAsync(DataTable dataTable, string tableName, IDbTransaction? dbTransaction = null);

    /// <summary>
    /// Sqlserver 数据拷贝
    /// </summary>
    /// <param name="items"></param>
    /// <param name="tableName"></param>
    /// <param name="dbTransaction"></param>
    void SqlServerBulkCopy(List<T> items, string? tableName = null, IDbTransaction? dbTransaction = null);

    /// <summary>
    /// Sqlserver 数据拷贝
    /// </summary>
    /// <param name="items"></param>
    /// <param name="tableName"></param>
    /// <param name="dbTransaction"></param>
    Task SqlServerBulkCopyAsync(List<T> items, string? tableName = null, IDbTransaction? dbTransaction = null);

    #endregion

    #region Mysql 数据批量拷贝

    /// <summary>
    /// mysql 批量拷贝数据
    /// <para>
    /// 需要开启服务端 mysql 的本地数据加载功能开关
    /// </para>
    /// <para>
    /// 1、请先查看本地加载数据是否开启使用此命令：SHOW GLOBAL VARIABLES LIKE 'local_infile';
    /// </para>
    /// <para>
    /// 2、使用此命令修改为 true 开启本地数据加载功能：SET GLOBAL local_infile = true;
    /// </para>
    /// <para>
    /// 3、连接字符串中添加此属性：AllowLoadLocalInfile=true
    /// </para>
    /// </summary>
    /// <param name="dataTable"></param>
    /// <param name="tableName"></param>
    /// <param name="dbTransaction"></param>
    void MySqlBulkCopy(DataTable dataTable, string tableName, IDbTransaction? dbTransaction = null);

    /// <summary>
    /// mysql 批量拷贝数据
    /// <para>
    /// 需要开启服务端 mysql 的本地数据加载功能开关
    /// </para>
    /// <para>
    /// 1、请先查看本地加载数据是否开启使用此命令：SHOW GLOBAL VARIABLES LIKE 'local_infile';
    /// </para>
    /// <para>
    /// 2、使用此命令修改为 true 开启本地数据加载功能：SET GLOBAL local_infile = true;
    /// </para>
    /// <para>
    /// 3、连接字符串中添加此属性：AllowLoadLocalInfile=true
    /// </para>
    /// </summary>
    /// <param name="dataTable"></param>
    /// <param name="tableName"></param>
    /// <param name="dbTransaction"></param>
    /// <returns></returns>
    Task MySqlBulkCopyAsync(DataTable dataTable, string tableName, IDbTransaction? dbTransaction = null);

    /// <summary>
    /// mysql 批量拷贝数据
    /// <para>
    /// 需要开启服务端 mysql 的本地数据加载功能开关
    /// </para>
    /// <para>
    /// 1、请先查看本地加载数据是否开启使用此命令：SHOW GLOBAL VARIABLES LIKE 'local_infile';
    /// </para>
    /// <para>
    /// 2、使用此命令修改为 true 开启本地数据加载功能：SET GLOBAL local_infile = true;
    /// </para>
    /// <para>
    /// 3、连接字符串中添加此属性：AllowLoadLocalInfile=true
    /// </para>
    /// </summary>
    /// <param name="items"></param>
    /// <param name="tableName"></param>
    /// <param name="dbTransaction"></param>
    void MySqlBulkCopy(List<T>? items, string? tableName = null, IDbTransaction? dbTransaction = null);

    /// <summary>
    /// mysql 批量拷贝数据
    /// <para>
    /// 需要开启服务端 mysql 的本地数据加载功能开关
    /// </para>
    /// <para>
    /// 1、请先查看本地加载数据是否开启使用此命令：SHOW GLOBAL VARIABLES LIKE 'local_infile';
    /// </para>
    /// <para>
    /// 2、使用此命令修改为 true 开启本地数据加载功能：SET GLOBAL local_infile = true;
    /// </para>
    /// <para>
    /// 3、连接字符串中添加此属性：AllowLoadLocalInfile=true
    /// </para>
    /// </summary>
    /// <param name="items"></param>
    /// <param name="tableName"></param>
    /// <param name="dbTransaction"></param>
    /// <returns></returns>
    Task MySqlBulkCopyAsync(List<T> items, string? tableName = null, IDbTransaction? dbTransaction = null);

    #endregion

    #region Npgsql 数据批量拷贝

    /// <summary>
    /// Sqlserver 数据拷贝
    /// </summary>
    /// <param name="dataTable"></param>
    /// <param name="tableName"></param>
    /// <param name="ignoreColumns"></param>
    void NpgsqlBulkCopy(DataTable dataTable, string tableName, params string[] ignoreColumns);

    /// <summary>
    /// Sqlserver 数据拷贝
    /// </summary>
    /// <param name="dataTable"></param>
    /// <param name="tableName"></param>
    /// <param name="ignoreColumns"></param>
    /// <returns></returns>
    Task NpgsqlBulkCopyAsync(DataTable dataTable, string tableName, params string[] ignoreColumns);

    /// <summary>
    /// Sqlserver 数据拷贝
    /// </summary>
    /// <param name="items"></param>
    /// <param name="tableName"></param>
    /// <param name="ignoreColumns"></param>
    void NpgsqlBulkCopy(List<T> items, string? tableName = null, params string[] ignoreColumns);

    /// <summary>
    /// Sqlserver 数据拷贝
    /// </summary>
    /// <param name="items"></param>
    /// <param name="tableName"></param>
    /// <param name="ignoreColumns"></param>
    Task NpgsqlBulkCopyAsync(List<T> items, string? tableName = null, params string[] ignoreColumns);

    #endregion
}